package cppweb.spring;

import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import stdx.Utils;
import webx.WebApp;
import webx.LogFile;
import stdx.TaskQueue;
import java.util.List;
import java.util.ArrayList;
import java.io.PrintStream;
import java.lang.reflect.Field;
import org.springframework.boot.Banner;
import org.springframework.core.env.Environment;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.beans.factory.annotation.Autowired;

public class SpringWebApp extends WebApp{
	static List<ApplicationContext> contexts = new ArrayList<>();

	public SpringWebApp(){
		Field[] fields = this.getClass().getDeclaredFields();
		try{
			for (Field field : fields){
				if (field.getAnnotation(Autowired.class) == null) continue;
				field.setAccessible(true); field.set(this, getBean(field.getType()));
			}
		}
		catch(Exception e){
			LogFile.Error(e);
		}
	}

	public static void initialize(Class clazz){
		TaskQueue.Instance().push(new Runnable(){
			public void run(){
				SpringLogger.setup();
				String name = clazz.getName().toLowerCase();
				SpringApplication app = new SpringApplication(clazz);
				for (int i = 0; i < 10 && Utils.IsEmpty(Utils.GetConfigFilePath()); i++) Utils.Sleep(100);
				app.setBanner(new Banner(){
					@Override
					public void printBanner(Environment environment, Class clazz, PrintStream out){
						LogFile.Notice(String.format("initialize springboot application[%s]", name));
					}
				});
				String[] args = new String[]{"--spring.config.location=" + Utils.GetConfigFilePath()};
				contexts.add(app.run(args));
				SpringLogger.finish();
			}
		}, 1000);
	}

	public static <T> T getBean(Class<T> clazz){
		for (ApplicationContext context : contexts){
			try {
				return context.getBean(clazz);
			}
			catch (NoSuchBeanDefinitionException e){
			}
		}
		return null;
	}
}